<?php

class TestDjFields extends UnitTestCase {

    /*function testRendering() {
        $f = new DjField()
    }*/

    function testBooleanField() {
        $this->sendMessage("testing DjBooleanField");
        $f = new DjBooleanField();
        $this->_assertCleanException($f, false, "clean(false) should raise DjValidationError when required");

        $this->assertEqual($f->clean('1'), true, "clean('1') should return true");
        $this->assertEqual($f->clean(1), true, "clean(1) should return true");

        $f = new DjBooleanField(array('required' => false));
        $this->assertEqual($f->clean(false), false, "clean(false) should return false and raise nothing when required is false");

        // html rendering
        $this->_testRendering($f, 'bool', '<input +type="checkbox" +name="bool" +value="1" +id="id_bool" +/>');
        // $this->dump($f);
    }

    function testCharField() {
        $this->sendMessage("testing DjCharField");

        $f = new DjCharField();
        $this->_assertCleanException($f, '', "clean('') should raise DjValidationError when required");

        $f = new DjCharField(array(
            'min_length' => 10
            , 'max_length' => 20
            , 'initial' => 'type here'));
        $this->_assertCleanException($f, 'too short');
        $this->_assertCleanException($f, 'this is way too long to validate 20 chars max, isnt it ?');
        $ok = 'I am just right';
        $this->assertEqual($f->clean($ok), $ok);

        // html rendering
        $this->_testRendering($f, 'name'
            , '<input type="text" +name="name" +id=".+" +value="type here" +maxlength="20" +/>', 'type here');
        $this->_testRendering($f, 'name'
            , '<input type="text" +name="name" +id=".+" +value="yes i can type" +maxlength="20" +/>', 'yes i can type');

    }

    function testText() {

        $f = new DjcharField(array(
            'widget' => new DjTextarea()
        ));

        $html = '<textarea name="name" id="id_name">lorem ipsum</textarea>';
        $this->_testRendering($f, 'name'
            , $html, 'lorem ipsum');
    }

    /**
     *
     */
    function testChoiceField() {
        $this->sendMessage("testing DjChoiceField");
        // numeric choices array
        $f = new DjChoiceField(array(
            'choices' => array('one', 'two', 'three')));
        $this->_assertCleanException($f, '', 'clean() should raise an exception if empty');
        $this->_assertCleanException($f, 'four', 'clean() should raise an exception on invalid choice');
        // html rendering
        $html = '<select name="name" +>'
        .'(<option value=".+">.+</option>){3}'
        .'</select>';
        $this->_testRendering($f, 'name', $html);

        // and now bound with string labels


    }

    function testDateField() {
        $this->sendMessage("testing DjDateField");
        $f = new DjDateField();
        $this->_assertCleanException($f, '', "clean('') should raise DjValidationError when required");
    }

    function testSlugField() {
        $this->sendMessage("testing DjSlugField");
    }

    /**
     * paints pass when field->clean() raise an exception, paints error elsewhere
     * @param DjField $field
     * @param mixed $value value to pass to clean
     * @param string $message
     */
    function _assertCleanException($field, $value) {
        try {
            $field->clean($value);
            $this->fail("$value raised no exception");
            $this->dump($field);
        } catch (Exception $e) {
            $this->assertIsA($e, 'DjValidationError'
                , 'clean('.$value.') raised a '
                .get_class($e).' : '.$e->getMessage());
        }
    }

    /**
     * paints pass when field->clean() raise no exception
     * @param DjField $field
     * @param mixed $value value to pass to clean
     * @param string $message
     */
    function _assertNoCleanException($field, $value) {
        try {
            $field->clean($value);
            $this->pass("$value raised no exception");
        } catch (DjValidationError $e) {
            $this->fail($message.$e->getMessage());
        }
    }

    /**
     * tests field's rendering
     * @param DjField $field
     * @param string $name
     * @param string $regex
     * @param mixed $value
     */
    protected function _testRendering($field, $name, $regex, $value=null) {
        $field->bound($name, $value);
        $rendered = strval($field);

        if (!$this->assertTrue(ereg($regex, $rendered), "test HTML rendering")) {
            $this->dump(htmlentities($rendered));
            $this->dump(htmlentities($regex));
        }
        /*$rendered = strval($field);
        if (!$this->assertWantedPattern($rendered, $html, "test HTML rendering")) {
            $this->dump(htmlentities($rendered));
        }*/
    }
}